package com.smart.community.work.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.smart.community.commons.annotation.ApiLog;
import com.smart.community.commons.enums.ApiLogOperationType;
import com.smart.community.commons.result.Result;
import com.smart.community.commons.utils.SecurityUtils;
import com.smart.community.work.entity.SecurityEvent;
import com.smart.community.work.entity.SecurityPatrol;
import com.smart.community.work.entity.SecurityRoute;
import com.smart.community.work.entity.Visitor;
import com.smart.community.work.service.SecurityService;
import com.smart.community.work.vo.SecurityEventVO;
import com.smart.community.work.vo.SecurityPatrolVO;
import com.smart.community.work.vo.SecurityRouteVO;
import com.smart.community.work.vo.VisitorVO;
import com.smart.community.work.dto.SecurityRouteQueryDTO;
import com.smart.community.work.dto.SecurityRouteCreateDTO;
import com.smart.community.work.dto.SecurityRouteUpdateDTO;
import com.smart.community.work.dto.SecurityPatrolQueryDTO;
import com.smart.community.work.dto.SecurityEventQueryDTO;
import com.smart.community.work.dto.VisitorQueryDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 安保管理控制器
 * 
 * 严格按照《Java后端SpringBoot代码开发规范_重构版.md》Controller规范实现：
 * - 统一返回格式：使用Result统一包装返回结果
 * - 参数验证：使用@Valid注解进行参数验证
 * - 异常处理：使用统一的异常处理机制，异常往外抛
 * - 日志记录：使用@Slf4j注解记录关键操作日志，避免Controller层log.error
 * - 权限控制：使用SecurityUtils获取当前用户信息
 * - 完整注释：所有方法都有完整的JavaDoc注释
 * - API文档：使用Swagger注解生成API文档
 * 
 * @author Wu.Liang
 * @since 2025-01-30
 * @version 1.0.0
 */
@Slf4j
@RestController
@RequestMapping("/work/security")
@RequiredArgsConstructor
@Validated
@Tag(name = "安保管理", description = "安保管理相关接口")
public class SecurityController {

    private final SecurityService securityService;

    // ========================= 巡逻路线管理 =========================

    /**
     * 分页查询巡逻路线
     * 
     * @param pageNum 页码
     * @param pageSize 每页大小
     * @param routeName 路线名称
     * @param routeType 路线类型
     * @param status 状态
     * @return 巡逻路线分页数据
     */
    @GetMapping("/route/page")
    @Operation(summary = "分页查询巡逻路线", description = "分页查询巡逻路线列表，支持基于数据权限的社区过滤")
    public Result<IPage<SecurityRouteVO>> getRoutePage(
            @Parameter(description = "页码") @RequestParam(defaultValue = "1") Integer pageNum,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "10") Integer pageSize,
            @Parameter(description = "路线名称") @RequestParam(required = false) String routeName,
            @Parameter(description = "路线类型") @RequestParam(required = false) String routeType,
            @Parameter(description = "状态") @RequestParam(required = false) Integer status) throws Exception {
        
        // 权限控制：获取当前用户信息
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (currentUserId == null) {
            log.warn("用户未登录，无法查询安保路线");
            return Result.fail("用户未登录");
        }
        
        log.info("分页查询安保路线，当前用户ID：{}，查询参数：pageNum={}, pageSize={}, routeName={}, routeType={}, status={}", 
                currentUserId, pageNum, pageSize, routeName, routeType, status);
        
        // 构建查询参数DTO
        SecurityRouteQueryDTO queryDTO = new SecurityRouteQueryDTO();
        queryDTO.setPageNum(pageNum);
        queryDTO.setPageSize(pageSize);
        queryDTO.setRouteName(routeName);
        queryDTO.setRouteType(routeType);
        queryDTO.setStatus(status);
        
        // 分页查询（带权限控制）
        Page<SecurityRouteVO> page = new Page<>(pageNum, pageSize);
        IPage<SecurityRouteVO> result = securityService.selectSecurityRoutePageWithPermission(page, queryDTO, currentUserId);
        return Result.success(result);
    }

    /**
     * 根据ID查询巡逻路线详情
     * 
     * @param id 路线ID
     * @return 巡逻路线详情
     */
    @GetMapping("/route/{id}")
    @Operation(summary = "获取路线详情", description = "根据ID查询巡逻路线详情")
    public Result<SecurityRouteVO> getRouteById(@Parameter(description = "路线ID") @PathVariable Long id) throws Exception {
        SecurityRouteVO result = securityService.selectSecurityRouteById(id);
        return Result.success(result);
    }

    /**
     * 创建巡逻路线
     * 
     * @param createDTO 巡逻路线创建DTO
     * @return 创建结果
     */
    @ApiLog(
        logTitle = "创建巡逻路线",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.ADD
    )
    @PostMapping("/route")
    @Operation(summary = "创建巡逻路线", description = "创建新的巡逻路线")
    public Result<Boolean> createRoute(@Valid @RequestBody SecurityRouteCreateDTO createDTO) throws Exception {
        Boolean result = securityService.createSecurityRoute(createDTO);
        return Result.success(result);
    }

    /**
     * 更新巡逻路线
     * 
     * @param id 路线ID
     * @param updateDTO 巡逻路线更新DTO
     * @return 更新结果
     */
    @ApiLog(
        logTitle = "更新巡逻路线",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.UPDATE
    )
    @PutMapping("/route/{id}")
    @Operation(summary = "更新巡逻路线", description = "更新巡逻路线信息")
    public Result<Boolean> updateRoute(@Parameter(description = "路线ID") @PathVariable Long id,
                                      @Valid @RequestBody SecurityRouteUpdateDTO updateDTO) throws Exception {
        updateDTO.setId(id);
        Boolean result = securityService.updateSecurityRoute(updateDTO);
        return Result.success(result);
    }

    /**
     * 删除巡逻路线
     * 
     * @param id 路线ID
     * @return 删除结果
     */
    @ApiLog(
        logTitle = "删除巡逻路线",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.DELETE
    )
    @DeleteMapping("/route/{id}")
    @Operation(summary = "删除巡逻路线", description = "删除巡逻路线")
    public Result<Boolean> deleteRoute(@Parameter(description = "路线ID") @PathVariable Long id) throws Exception {
        Long currentUserId = SecurityUtils.getCurrentUserId();
        Boolean result = securityService.deleteSecurityRoute(id, currentUserId);
        return Result.success(result);
    }

    // ========================= 巡逻记录管理 =========================

    /**
     * 分页查询巡逻记录
     * 
     * @param pageNum 页码
     * @param pageSize 每页大小
     * @param userId 用户ID
     * @param routeId 路线ID
     * @param status 状态
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 巡逻记录分页数据
     */
    @GetMapping("/patrol/page")
    @Operation(summary = "分页查询巡逻记录", description = "分页查询巡逻记录列表")
    public Result<IPage<SecurityPatrolVO>> getPatrolPage(
            @Parameter(description = "页码") @RequestParam(defaultValue = "1") Integer pageNum,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "10") Integer pageSize,
            @Parameter(description = "用户ID") @RequestParam(required = false) Long userId,
            @Parameter(description = "路线ID") @RequestParam(required = false) Long routeId,
            @Parameter(description = "状态") @RequestParam(required = false) Integer status,
            @Parameter(description = "开始日期") @RequestParam(required = false) String startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) String endDate) throws Exception {
        // 构建查询参数DTO
        SecurityPatrolQueryDTO queryDTO = new SecurityPatrolQueryDTO();
        queryDTO.setPageNum(pageNum);
        queryDTO.setPageSize(pageSize);
        queryDTO.setUserId(userId);
        queryDTO.setRouteId(routeId);
        queryDTO.setStatus(status);
        
        // 日期参数解析
        if (startDate != null && !startDate.trim().isEmpty()) {
            try {
                queryDTO.setStartDate(LocalDate.parse(startDate));
            } catch (Exception e) {
                log.error("解析开始日期失败: {}", startDate, e);
                return Result.fail("开始日期格式不正确，请使用 yyyy-MM-dd 格式");
            }
        }
        
        if (endDate != null && !endDate.trim().isEmpty()) {
            try {
                queryDTO.setEndDate(LocalDate.parse(endDate));
            } catch (Exception e) {
                log.error("解析结束日期失败: {}", endDate, e);
                return Result.fail("结束日期格式不正确，请使用 yyyy-MM-dd 格式");
            }
        }
        
        // 分页查询
        Page<SecurityPatrolVO> page = new Page<>(pageNum, pageSize);
        IPage<SecurityPatrolVO> result = securityService.selectSecurityPatrolPage(page, queryDTO);
        return Result.success(result);
    }

    /**
     * 根据用户ID查询巡逻记录
     * 
     * @param userId 用户ID
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 巡逻记录列表
     */
    @GetMapping("/patrol/user/{userId}")
    @Operation(summary = "查询用户巡逻记录", description = "根据用户ID查询巡逻记录")
    public Result<List<SecurityPatrolVO>> getPatrolByUserId(
            @Parameter(description = "用户ID") @PathVariable Long userId,
            @Parameter(description = "开始日期") @RequestParam(required = false) String startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) String endDate) throws Exception {
        
        // 参数验证
        if (userId == null) {
            return Result.fail("用户ID不能为空");
        }
        
        LocalDate start = null;
        LocalDate end = null;
        
        if (startDate != null && !startDate.trim().isEmpty()) {
            try {
                start = LocalDate.parse(startDate);
            } catch (Exception e) {
                log.warn("开始日期格式错误：{}", startDate, e);
                return Result.fail("开始日期格式错误");
            }
        }
        
        if (endDate != null && !endDate.trim().isEmpty()) {
            try {
                end = LocalDate.parse(endDate);
            } catch (Exception e) {
                log.warn("结束日期格式错误：{}", endDate, e);
                return Result.fail("结束日期格式错误");
            }
        }
        
        List<SecurityPatrolVO> result = securityService.selectSecurityPatrolByUserId(userId, start, end);
        return Result.success(result);
    }

    /**
     * 开始巡逻
     * 
     * @param securityPatrol 巡逻记录信息
     * @return 开始结果
     */
    @ApiLog(
        logTitle = "开始巡逻",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.ADD
    )
    @PostMapping("/patrol/start")
    @Operation(summary = "开始巡逻", description = "开始新的巡逻任务")
    public Result<Boolean> startPatrol(@Valid @RequestBody SecurityPatrol securityPatrol) throws Exception {
        Long currentUserId = SecurityUtils.getCurrentUserId();
        securityPatrol.setUserId(currentUserId);
        securityPatrol.setCreateBy(currentUserId);
        securityPatrol.setUpdateBy(currentUserId);
        
        Boolean result = securityService.startPatrol(securityPatrol);
        return Result.success(result);
    }

    /**
     * 巡逻签到
     * 
     * @param patrolId 巡逻记录ID
     * @param checkPointId 签到点ID
     * @param checkTime 签到时间
     * @param remark 签到备注
     * @return 签到结果
     */
    @PutMapping("/patrol/{patrolId}/check")
    @Operation(summary = "巡逻签到", description = "在指定检查点签到")
    public Result<Boolean> patrolCheckIn(
            @Parameter(description = "巡逻记录ID") @PathVariable Long patrolId,
            @Parameter(description = "签到点ID") @RequestParam Long checkPointId,
            @Parameter(description = "签到时间") @RequestParam String checkTime,
            @Parameter(description = "签到备注") @RequestParam(required = false) String remark) throws Exception {
        LocalDateTime checkDateTime = LocalDateTime.parse(checkTime);
        Boolean result = securityService.patrolCheckIn(patrolId, checkPointId, checkDateTime, remark);
        return Result.success(result);
    }

    /**
     * 结束巡逻
     * 
     * @param patrolId 巡逻记录ID
     * @param endTime 结束时间
     * @param summary 巡逻总结
     * @return 结束结果
     */
    @PutMapping("/patrol/{patrolId}/end")
    @Operation(summary = "结束巡逻", description = "结束巡逻任务")
    public Result<Boolean> endPatrol(
            @Parameter(description = "巡逻记录ID") @PathVariable Long patrolId,
            @Parameter(description = "结束时间") @RequestParam String endTime,
            @Parameter(description = "巡逻总结") @RequestParam(required = false) String summary) throws Exception {
        LocalDateTime endDateTime = LocalDateTime.parse(endTime);
        Boolean result = securityService.endPatrol(patrolId, endDateTime, summary);
        return Result.success(result);
    }

    // ========================= 安全事件管理 =========================

    /**
     * 分页查询安全事件
     * 
     * @param pageNum 页码
     * @param pageSize 每页大小
     * @param eventType 事件类型
     * @param severity 严重程度
     * @param status 状态
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 安全事件分页数据
     */
    @GetMapping("/event/page")
    @Operation(summary = "分页查询安全事件", description = "分页查询安全事件列表")
    public Result<IPage<SecurityEventVO>> getEventPage(
            @Parameter(description = "页码") @RequestParam(defaultValue = "1") Integer pageNum,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "10") Integer pageSize,
            @Parameter(description = "事件类型") @RequestParam(required = false) String eventType,
            @Parameter(description = "严重程度") @RequestParam(required = false) Integer severity,
            @Parameter(description = "状态") @RequestParam(required = false) Integer status,
            @Parameter(description = "开始日期") @RequestParam(required = false) String startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) String endDate) throws Exception {
        // 构建查询参数DTO
        SecurityEventQueryDTO queryDTO = new SecurityEventQueryDTO();
        queryDTO.setPageNum(pageNum);
        queryDTO.setPageSize(pageSize);
        queryDTO.setEventType(eventType);
        queryDTO.setSeverity(severity);
        queryDTO.setStatus(status);
        
        // 日期参数解析
        if (startDate != null && !startDate.trim().isEmpty()) {
            try {
                queryDTO.setStartDate(LocalDate.parse(startDate));
            } catch (Exception e) {
                log.error("解析开始日期失败: {}", startDate, e);
                return Result.fail("开始日期格式不正确，请使用 yyyy-MM-dd 格式");
            }
        }
        
        if (endDate != null && !endDate.trim().isEmpty()) {
            try {
                queryDTO.setEndDate(LocalDate.parse(endDate));
            } catch (Exception e) {
                log.error("解析结束日期失败: {}", endDate, e);
                return Result.fail("结束日期格式不正确，请使用 yyyy-MM-dd 格式");
            }
        }
        
        // 分页查询
        Page<SecurityEventVO> page = new Page<>(pageNum, pageSize);
        IPage<SecurityEventVO> result = securityService.selectSecurityEventPage(page, queryDTO);
        return Result.success(result);
    }

    /**
     * 根据ID查询安全事件详情
     * 
     * @param id 事件ID
     * @return 安全事件详情
     */
    @GetMapping("/event/{id}")
    @Operation(summary = "获取事件详情", description = "根据ID查询安全事件详情")
    public Result<SecurityEventVO> getEventById(@Parameter(description = "事件ID") @PathVariable Long id) throws Exception {
        SecurityEventVO result = securityService.selectSecurityEventById(id);
        return Result.success(result);
    }

    /**
     * 上报安全事件
     * 
     * @param securityEvent 安全事件信息
     * @return 上报结果
     */
    @ApiLog(
        logTitle = "上报安全事件",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.ADD
    )
    @PostMapping("/event")
    @Operation(summary = "上报安全事件", description = "上报新的安全事件")
    public Result<Boolean> reportEvent(@Valid @RequestBody SecurityEvent securityEvent) throws Exception {
        Long currentUserId = SecurityUtils.getCurrentUserId();
        securityEvent.setReporterId(currentUserId);
        securityEvent.setCreateBy(currentUserId);
        securityEvent.setUpdateBy(currentUserId);
        
        Boolean result = securityService.reportSecurityEvent(securityEvent);
        return Result.success(result);
    }

    /**
     * 处理安全事件
     * 
     * @param eventId 事件ID
     * @param handlerId 处理人ID
     * @param handleResult 处理结果
     * @param handleRemark 处理备注
     * @return 处理结果
     */
    @PutMapping("/event/{eventId}/handle")
    @Operation(summary = "处理安全事件", description = "处理安全事件")
    public Result<Boolean> handleEvent(
            @Parameter(description = "事件ID") @PathVariable Long eventId,
            @Parameter(description = "处理人ID") @RequestParam Long handlerId,
            @Parameter(description = "处理结果") @RequestParam String handleResult,
            @Parameter(description = "处理备注") @RequestParam(required = false) String handleRemark) throws Exception {
        Boolean result = securityService.handleSecurityEvent(eventId, handlerId, handleResult, handleRemark);
        return Result.success(result);
    }

    // ========================= 访客管理 =========================

    /**
     * 分页查询访客记录
     * 
     * @param pageNum 页码
     * @param pageSize 每页大小
     * @param visitorName 访客姓名
     * @param visitDate 访问日期
     * @param status 状态
     * @return 访客记录分页数据
     */
    @GetMapping("/visitor/page")
    @Operation(summary = "分页查询访客记录", description = "分页查询访客记录列表")
    public Result<IPage<VisitorVO>> getVisitorPage(
            @Parameter(description = "页码") @RequestParam(defaultValue = "1") Integer pageNum,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "10") Integer pageSize,
            @Parameter(description = "访客姓名") @RequestParam(required = false) String visitorName,
            @Parameter(description = "访问日期") @RequestParam(required = false) String visitDate,
            @Parameter(description = "状态") @RequestParam(required = false) Integer status) throws Exception {
        // 构建查询参数DTO
        VisitorQueryDTO queryDTO = new VisitorQueryDTO();
        queryDTO.setPageNum(pageNum);
        queryDTO.setPageSize(pageSize);
        queryDTO.setVisitorName(visitorName);
        queryDTO.setStatus(status);
        
        // 日期参数解析
        if (visitDate != null && !visitDate.trim().isEmpty()) {
            try {
                queryDTO.setVisitDate(LocalDate.parse(visitDate));
            } catch (Exception e) {
                log.error("解析访问日期失败: {}", visitDate, e);
                return Result.fail("访问日期格式不正确，请使用 yyyy-MM-dd 格式");
            }
        }
        
        // 分页查询
        Page<VisitorVO> page = new Page<>(pageNum, pageSize);
        IPage<VisitorVO> result = securityService.selectVisitorPage(page, queryDTO);
        return Result.success(result);
    }

    /**
     * 访客登记
     * 
     * @param visitor 访客信息
     * @return 登记结果
     */
    @ApiLog(
        logTitle = "访客登记",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.ADD
    )
    @PostMapping("/visitor")
    @Operation(summary = "访客登记", description = "登记新的访客")
    public Result<Boolean> registerVisitor(@Valid @RequestBody Visitor visitor) throws Exception {
        Long currentUserId = SecurityUtils.getCurrentUserId();
        visitor.setCreateBy(currentUserId);
        visitor.setUpdateBy(currentUserId);
        
        Boolean result = securityService.registerVisitor(visitor);
        return Result.success(result);
    }

    /**
     * 访客离开
     * 
     * @param visitorId 访客记录ID
     * @param leaveTime 离开时间
     * @return 离开结果
     */
    @PutMapping("/visitor/{visitorId}/leave")
    @Operation(summary = "访客离开", description = "记录访客离开时间")
    public Result<Boolean> visitorLeave(
            @Parameter(description = "访客记录ID") @PathVariable Long visitorId,
            @Parameter(description = "离开时间") @RequestParam String leaveTime) throws Exception {
        LocalDateTime leaveDateTime = LocalDateTime.parse(leaveTime);
        Boolean result = securityService.visitorLeave(visitorId, leaveDateTime);
        return Result.success(result);
    }

    // ========================= 统计查询 =========================

    /**
     * 获取安保统计信息
     * 
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 统计信息
     */
    @GetMapping("/statistics")
    @Operation(summary = "获取安保统计信息", description = "获取安保工作统计信息")
    public Result<Map<String, Object>> getSecurityStatistics(
            @Parameter(description = "开始日期") @RequestParam(required = false) String startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) String endDate) throws Exception {
        LocalDate start = startDate != null ? LocalDate.parse(startDate) : null;
        LocalDate end = endDate != null ? LocalDate.parse(endDate) : null;
        
        // 获取当前用户的物业公司ID
        Long propertyCompanyId = getCurrentUserPropertyCompanyId();
        
        Map<String, Object> result = securityService.getSecurityStatistics(propertyCompanyId, start, end);
        return Result.success(result);
    }
    
    /**
     * 获取当前用户的物业公司ID
     * @return 物业公司ID
     */
    private Long getCurrentUserPropertyCompanyId() {
        try {
            // 这里应该从用户信息中获取物业公司ID
            // 暂时返回null，实际应该从用户服务获取
            return null;
        } catch (Exception e) {
            log.warn("获取用户物业公司ID失败", e);
            return null;
        }
    }

    /**
     * 获取用户安保统计
     * 
     * @param userId 用户ID
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 用户统计信息
     */
    @GetMapping("/statistics/user/{userId}")
    @Operation(summary = "获取用户安保统计", description = "获取指定用户的安保工作统计")
    public Result<Map<String, Object>> getUserSecurityStatistics(
            @Parameter(description = "用户ID") @PathVariable Long userId,
            @Parameter(description = "开始日期") @RequestParam(required = false) String startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) String endDate) throws Exception {
        LocalDate start = startDate != null ? LocalDate.parse(startDate) : null;
        LocalDate end = endDate != null ? LocalDate.parse(endDate) : null;
        
        Map<String, Object> result = securityService.getUserSecurityStatistics(userId, start, end);
        return Result.success(result);
    }
}